package com.kt.coroutinedemo.Netty

import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled
import io.netty.channel.ChannelFutureListener
import io.netty.channel.ChannelHandlerAdapter
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.timeout.IdleState
import io.netty.handler.timeout.IdleStateEvent
import io.netty.handler.timeout.ReadTimeoutException
import io.netty.handler.timeout.WriteTimeoutException
import io.netty.util.CharsetUtil


/**
 * @Author Xzh
 * @Date 2025/6/5
 * @Description
 */
class IdleStateEventHandler : ChannelHandlerAdapter() {

    // 心跳消息
    private val HEARTBEAT: ByteBuf = Unpooled.unreleasableBuffer(
        Unpooled.copiedBuffer("HEARTBEAT", CharsetUtil.UTF_8)
    )

    override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any?) {
        if (evt is IdleStateEvent) {
            when (evt.state()) {
                IdleState.READER_IDLE ->                     // 读空闲：服务器太久没有发送数据
                    handleReaderIdle(ctx)

                IdleState.WRITER_IDLE ->                     // 写空闲：发送心跳包保持连接
                    sendHeartbeat(ctx)

                IdleState.ALL_IDLE -> {}
            }
        }
    }

    private fun handleReaderIdle(ctx: ChannelHandlerContext) {
        println("读空闲超时，关闭连接")
        ctx.close()
    }

    private fun sendHeartbeat(ctx: ChannelHandlerContext) {
        println("发送心跳包")
        ctx.writeAndFlush(HEARTBEAT.duplicate())
            .addListener(ChannelFutureListener.CLOSE_ON_FAILURE)
    }

    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        if (cause is ReadTimeoutException) {
            println("读超时异常: " + cause.message)
            ctx.close()
        } else if (cause is WriteTimeoutException) {
            println("写超时异常: " + cause.message)
            // 可选择重试或关闭
        } else {
            ctx.fireExceptionCaught(cause)
        }
    }
}